package com.ksd.utils.code;

import cn.hutool.core.codec.Base64Encoder;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

/**
 * @author ShangHai
 * @date 2019/12/04 22:08
 */
public class QRCodeUtil {

    /**
     * 生成二维码图片并返回
     * @param content 二维码存储的内容
     * @param width   指定二维码的宽度
     * @param height  指定二维码的高度
     * @return
     * @throws Exception
     */
    public static BufferedImage createQrCodeImage(String content, int width, int height) throws Exception{
        Hashtable hints = new Hashtable();
        //指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        //生成二维码矩阵
        BitMatrix bitMatrix =
                new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        //获取矩阵宽度、高度,生成二维码图片
        BufferedImage image = new BufferedImage(bitMatrix.getWidth(),bitMatrix.getHeight(),BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }

    /**
     * 往二维码中插入一个LOGO,也可以在底部插入一行字符
     * @param image 需要插入LOGO的二维码
     * @param logoPath  LOGO的路径
     * @param showBottomText  底部需要显示的字符
     * @return
     */
    public static BufferedImage megerLoGo(BufferedImage image,String logoPath,String showBottomText) throws IOException {
        Graphics2D gs = image.createGraphics();

        //1.加入LOGO水印效果
        if(logoPath!=null && !"".equals(logoPath)){
            //1.1 载入LOGO图片
            BufferedImage logoImage = ImageIO.read(new File(logoPath));
            //1.2 考虑到LOGO图片将插入到二维码中间,建议大小不要超过二维码的1/5
            int width = image.getWidth()/8;
            int height = image.getHeight()/8;
            //1.3 LOGO居中显示
            int x = (image.getWidth() - width)/2;
            int y = (image.getHeight() - height)/2;
            gs.drawImage(logoImage,x,y,width,height,null);
            logoImage.flush();
        }

        //2.二维码图片底部插入文字
        if(showBottomText!=null && !"".equals(showBottomText)){
            //2.1 设置字体样式
            Font font = new Font("微软雅黑", Font.PLAIN, 14);
            gs.setColor(Color.BLACK);
            gs.setFont(font);
            //2.2 字体显示位置
            int x = (image.getWidth() - getWatermarkLength(showBottomText, gs))/2;
            int y = image.getHeight()-10;
            gs.drawString(showBottomText, x, y);
        }
        //销毁图形界面资源
        gs.dispose();
        return image;
    }

    /**
     * 将图片转换成base64的字符串并返回
     * @param image 需要进行转换的图片
     * @return
     * @throws Exception
     */
    public static String imageToBase64(BufferedImage image) throws Exception{
        String base64 = "data:image/jpg;base64,";
        //新建字符数组输出流
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        //利用ImageIO类提供的write方法，将图片以jpg的数据模式写入字符数组输出流
        ImageIO.write(image,"jpg",os);
        //从流中获取数据数组
        byte[] bytes = os.toByteArray();
        //将数据数组转换成base64字符串
        base64 += Base64Encoder.encode(bytes);
        return base64;
    }

    /**
     * 获取水印字体的长度
     * @param fontString
     * @param gs
     * @return
     */
    public static int getWatermarkLength(String fontString,Graphics2D gs){
        return gs.getFontMetrics(gs.getFont()).charsWidth(fontString.toCharArray(),0,fontString.length());
    }

}
